home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr47 / asmlib40.zip / DATA.DOC < prev    next >
Text File  |  1995-02-24  |  48KB  |  1,512 lines

  1.  
  2. *******************************  DATA  *************************************
  3.  
  4. ASMLIB data manipulation subroutines Copyright (C) 1991 - 1995 Douglas Herr
  5. all rights reserved
  6.  
  7. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  8.  
  9. CHRDEL:      deletes a character from a string
  10. CHRNDEL:     deletes a character from a string of known length
  11.              The resulting space is closed by moving the remaining
  12.              characters forward
  13. Source:      chrdel.asm (strlen.asm)
  14.  
  15. Call with:   DS:[BX] pointing to an ASCIIZ string
  16.              (chrndel only) CX = current string length
  17.              AX = offset from DS:[BX] to character to delete
  18. Returns:     CX = new string length
  19. Uses:        CX
  20. Example:     lea   bx,string          ; DS:[BX] points to string
  21.              mov   ax,3               ; delete character at DS:[BX+3]
  22.              call  chrdel             ; delete the character, shorten string
  23.  
  24.  
  25. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  26.  
  27. COLORATTR:   calculate a color attribute for ASMLIB's text-mode subroutines.
  28.              Intended for 16-color text modes.
  29. Source:      coloratt.asm
  30. Call with:   AL = foreground color (0 - 15)
  31.              AH = background color (0 - 15)
  32. Returns:     AH = color attribute
  33. Uses:        AX
  34. Example:
  35.  
  36. include      asm.inc
  37.  
  38.       mov    al,hired            ; bright red
  39.       mov    ah,blue             ; blue
  40.       call   colorattr           ; this should get their attention
  41.       mov    warning,ah          ; save the attribute
  42.  
  43. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  44.  
  45. CSET:        centers a string in a fixed field
  46. Source:      cset.asm (strlen.asm)
  47.  
  48. Call with:   ES:[DI] = address of field string
  49.              DS:[SI] = address of string to be centered in the field
  50.              Both strings must be zero-terminated (ASCIIZ).  The field
  51.              string may not contain any nul characters except for the
  52.              terminator.
  53. Returns:     CF = 0 if no error
  54.              CF = 1 if string was truncated to fit in the field
  55. Uses:        CF; all other flags and registers are saved
  56. Example:     mov   ax,@data             ; in this case, both strings
  57.              mov   ds,ax                ; are in DGROUP
  58.              mov   es,ax
  59.              assume es:@data, ds:@data
  60.              lea   di,field             ; field string
  61.              lea   si,source            ; string to be centered in field
  62.              call  cset
  63.  
  64.  
  65. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  66.  
  67. DAYNAME:     returns a pointer to an ASCII string for specified day
  68.              of the week
  69. Source:      dname.asm ($mname.asm)
  70.  
  71. Call with:   AX = day of week (1 - 7, Sunday = 1)
  72. Returns:     ES:[BX] = pointer to day name string
  73.              CX = length of new string
  74.              Note that the day name string is not zero-terminated
  75.              strndup may be used to copy the string to the near heap
  76. Uses:        ES, BX, CX
  77. Example:     mov    ax,day
  78.              call   dayname
  79.  
  80.  
  81.  
  82. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  83.  
  84. FILL4, FILL4b: fill a buffer with specified 4-byte data
  85. Source:        tiny, small & medium: fill4.asm
  86.                huge: fill4.asm (lowES2hi.asm)
  87.  
  88. Call with:   DS:[SI] pointing to 4-byte data (integer, float or other)
  89.              ES:[DI] pointing to buffer
  90.              CX = number of 4-byte data blocks to fill in buffer
  91.              Fill4b: BX = byte increment between data blocks
  92. Returns:     nothing
  93. Uses:        nothing
  94. Example:
  95.  
  96. include asm.inc
  97.  
  98. extrn   fill4:proc
  99.  
  100. .data
  101. wonowon dd 101.      ; float4 value
  102. farseg  dw ?         ; program allocates buffer, stores seg address here
  103.  
  104. .code
  105. program fragment assumes DS:@data
  106.         .
  107.         .
  108.         .
  109.         mov   es,farseg
  110.         xor   di,di      ; start at beginning of far segment
  111.         lea   si,wonowon ; fill every other 4-byte block in far segment
  112.         mov   bx,8       ; skip 4 bytes between data blocks
  113.         mov   cx,25      ; do it 25 times
  114.         cal   fill4
  115.  
  116.  
  117.  
  118. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  119.  
  120. FILL8, FILL8b: fill a buffer with specified 8-byte data
  121. Source:        tiny, small & medium: fill8.asm
  122.                huge: fill8.asm (lowES2hi.asm)
  123.  
  124. Call with:   DS:[SI] pointing to 8-byte data (integer, float or other)
  125.              ES:[DI] pointing to buffer
  126.              CX = number of 8-byte data blocks to fill in buffer
  127.              Fill8b: BX = byte increment between data blocks
  128. Returns:     nothing
  129. Uses:        nothing
  130. Example:     see Fill4
  131.  
  132.  
  133.  
  134.  
  135. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  136.  
  137. FSTRISTR:    search for a string in a disk file, case insensetive
  138. Source:      fstristr.asm (strlen.asm, $strstr.asm, strnupr.asm)
  139.  
  140. FSTRSTR:     search for a string in a disk file, case sensetive
  141. Source:      fstrstr.asm (strlen.asm, $strstr.asm)
  142.  
  143. Call with:   BX = file handle, DS:[SI] points to string to find
  144.              The file must have been opened with read access, and at least
  145.              64k DOS memory must be free.  See STARTUP.ASM and ENDPROG.ASM.
  146. Returns:     if CF = 0, DX:AX is the offset of the string in the file
  147.              if CF = 1: memory not available if AX = DX = 0
  148.                         string not found if AX = DX = -1
  149.                         error reading file if AX = DX = -2
  150. Uses:        AX, DX, flags
  151.  
  152. Example:
  153.  
  154. extrn   fstrstr:proc
  155.  
  156. .data
  157. string   db 'A String In The File',0
  158. filename db 'anyold.fil',0
  159.  
  160. .code
  161. yoursub proc
  162.         mov      dx,offset filename
  163.         mov      ax,3D00h          ; open the file with read access
  164.         int      21h
  165.         jc       no_good
  166.         mov      bx,ax
  167.         mov      si,offset string  ; DS:[SI] points to the string
  168.         call     fstrstr
  169.         jc       no_good           ; returns with DX = high word of
  170.                                    ; string position, AX = low word
  171.  
  172.  
  173. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  174.  
  175. GETCMD:      isolates command line parameters
  176.              GetCMD assumes that parameters are separated by
  177.              one or more spaces
  178. Source:      getcmd.asm
  179.  
  180. Call with:   ES = PSP segment (see STARTUP.ASM; not requried with TINY model)
  181.              AX = parameter number (first command line parameter = 0)
  182. Returns:     ES:[BX] pointing to command line parameter
  183.              CX = length of parameter string
  184.              CX = 0 if no command parameter(AX)
  185.              Note: the string at ES:[BX] is not zero-terminated
  186. Uses:        BX
  187. Example:
  188.  
  189. include asm.inc
  190.  
  191. extrn  getcmd:proc
  192.  
  193. .data
  194. extrn  pspseg:word        ; PSP segment saved by startup code
  195.  
  196. .code
  197.        .
  198.        .
  199.        .
  200.        mov    es,pspseg
  201.        mov    ax,0        ; get first parameter
  202.        call   getcmd      ; returns with ES:[BX] pointing to parameter
  203.                           ; and CX = length of parameter
  204.        jcxz   no_parameters
  205.        
  206.  
  207.  
  208. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  209.  
  210. I2TOSTR:     convert an integer value to an ASCIIZ string
  211. Source:      i2tostr.asm
  212.  
  213. I4TOSTR:     convert a long integer value to an ASCIIZ string
  214. Source:      i4tostr.asm
  215.  
  216.              ASMLIB's TPrint, GPrint and other 'print' subroutines require
  217.              a string argument.  Numeric data must be converted to a string
  218.              before printing.
  219.  
  220. Call with:   DS:[SI] pointing to a buffer space
  221.              (i2tostr) AX = integer value
  222.              (i4tostr) DX:AX = long integer value
  223.              i2tostr requires a 7-byte (or greater) buffer;
  224.              i4tostr requires a 12-byte (or greater) buffer
  225. Returns:     ASCIIZ string at DS:[SI]; numerals are right-justified
  226. Uses:        nothing; all registers and flags are saved
  227. Supports:    (i2tostr) signed 2-byte integers
  228.              (i4tostr) signed 4-byte integers
  229. Example:
  230.  
  231. include asm.inc
  232.  
  233. extrn  i2tostr:proc
  234.  
  235. .data
  236. nbuffer  db 7 dup(?)
  237.  
  238. .code
  239.  
  240.        .
  241.        .
  242.        .
  243.        mov   ax,@data
  244.        mov   ds,ax         ; numeric buffer is in DGROUP
  245.        assume  ds:@data
  246.        lea   si,nbuffer
  247.        mov   ax,32750      ; integer value
  248.        call  i2tostr
  249.  
  250.  
  251.  
  252. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  253.  
  254. LOWDS2HI:    converts low DS:high SI address to high DS:low SI
  255.              this is handy for data structures over 64k
  256. Source:      lowds2hi.asm
  257.  
  258. Call with:   DS:[SI] = address to convert
  259. Returns:     DS:[SI] = converted address; SI <= 15
  260. Uses:        DS, SI; all other registers and flags are saved
  261. Example:
  262.  
  263. extrn   lowDS2hi:proc
  264.  
  265. .code
  266.         .
  267.         .
  268.         .
  269.         mov   ds,hugeseg
  270.         mov   si,next_data
  271.         call  lowDS2hi       ; ready to address next (65535-15) bytes
  272.  
  273.  
  274. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  275.  
  276. LOWES2HI:    converts low ES:high DI address to high ES:low DI
  277.              this is handy for data structures over 64k
  278. Source:      lowes2hi.asm
  279.  
  280. Call with:   ES:[DI] = address to convert
  281. Returns:     ES:[DI] = converted address; DI <= 15
  282. Uses:        ES, DI; all other registers and flags are saved
  283. Example:
  284.  
  285. extrn   lowES2hi:proc
  286.  
  287. .code
  288.         .
  289.         .
  290.         .
  291.         mov   es,hugeseg
  292.         mov   di,next_data
  293.         call  lowES2hi       ; ready to address next (65535-15) bytes
  294.  
  295.  
  296.  
  297. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  298.  
  299. LSET:        left-justifies a string in a fixed field
  300. Source:      lset.asm (strlen.asm)
  301.  
  302. Call with:   ES:[DI] = address of field string
  303.              DS:[SI] = address of string to be justified in the field
  304.              Both strings must be zero-terminated (ASCIIZ).  The field
  305.              string may not contain any NUL characters except for the
  306.              terminator.
  307. Returns:     CF = 0 if no error
  308.              CF = 1 if string was truncated to fit in the field
  309. Uses:        CF
  310.              all other flags and registers saved
  311. Example:     mov   ax,@data             ; in this case, both strings
  312.              mov   ds,ax                ; are in DGROUP
  313.              mov   es,ax
  314.              assume es:@data, ds:@data
  315.              lea   di,field             ; field string
  316.              lea   si,source            ; string to be justified in field
  317.              call  lset
  318.  
  319.  
  320. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  321.  
  322. LTRIM:       remove leading blanks from an ASCIIZ string
  323. Source:      ltrim.asm (strlen.asm)
  324.  
  325. Call with:   DS:[BX] pointing to string
  326. Returns:     CX = new string length
  327. Uses:        CX
  328. Example:     lea    bx,string
  329.              call   ltrim
  330.  
  331.  
  332.  
  333.  
  334. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  335.  
  336. MAXI2, MAXI2b: find maximum value in a signed integer array
  337. Source:        tiny, small & medium models: maxi2.asm
  338.                huge model: maxi2.asm (lowDS2hi.asm)
  339.  
  340. MINI2, MINI2b: find minimum value in a signed integer array
  341. Source:        tiny, small & medium models: mini2.asm
  342.                huge model: mini2.asm (lowDS2hi.asm)
  343.  
  344. MAXU2, MINU2b: find maximum value in an unsigned integer array
  345. Source:        tiny, small & medium models: maxu2.asm
  346.                huge model: maxu2.asm (lowDS2hi.asm)
  347.  
  348. MINU2, MINU2b: find minimum value in an unsigned integer array
  349. Source:        tiny, small & medium models: minu2.asm
  350.                huge model: minu2.asm (lowDS2hi.asm)
  351.  
  352. Call with:   ES:[DI] pointing to the array
  353.              CX = number of array elements
  354.              For max/min?2b, call with BX = byte increment between
  355.              array elements.  Max/min?2 assume increment = 2.
  356. Returns:     AX = array element number with maximum value
  357.              see example to calculate address of maximum value
  358.              if subroutine was called with CX = 0, CF = 1
  359. Uses:        AX, CF
  360. Example:
  361.  
  362. include asm.inc
  363.  
  364. extrn  maxi2:proc
  365.  
  366. .data
  367.  
  368. integers     dw 140 dup(0)
  369.  
  370. .code
  371.              .     ; program establishes array values
  372.              .
  373.              .
  374.              mov    ax,@data
  375.              mov    es,ax
  376.              assume es:@data
  377.              lea    di,integers
  378.              mov    cx,140        ; search the entire array
  379.              call   maxi2
  380.              shl    ax,1          ; convert word offset to byte offsest
  381.              add    di,ax         ; ES:[DI] points to the maximum value
  382.                                   ; With max/min?2b, the offset of the
  383.                                   ; value is DI + (AX * BX).
  384.  
  385. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  386.  
  387. MAXI4, MAXI4b: find maximum value in a signed 4-byte integer array
  388. Source:        tiny, small & medium models: maxi4.asm
  389.                huge model: maxi4.asm (lowDS2hi.asm)
  390.  
  391. MINI4, MINI4b: find minimum value in a signed 4-byte integer array
  392. Source:        tiny, small & medium models: mini4.asm
  393.                huge model: mini4.asm (lowDS2hi.asm)
  394.  
  395. MAXU4, MAXU4b: find maximum value in an unsigned 4-byte integer array
  396. Source:        tiny, small & medium models: maxu4.asm
  397.                huge model: maxu4.asm (lowDS2hi.asm)
  398.  
  399. MINU4, MINU4b: find minimum value in an unsigned 4-byte integer array
  400. Source:        tiny, small & medium models: minu4.asm
  401.                huge model: minu4.asm (lowDS2hi.asm)
  402.  
  403. Call with:   ES:[DI] pointing to the array
  404.              CX = number of array elements
  405.              For max/min?4b, call with BX = byte increment between
  406.              array elements.  Max/min?4 assume increment = 4.
  407. Returns:     AX = array element number with maximum value
  408.              see example to calculate address of maximum value.
  409.              if subroutine was called with CX = 0, CF = 1
  410. Uses:        AX, CF
  411. Example:
  412.  
  413. include asm.inc
  414.  
  415. extrn  maxi4:proc
  416.  
  417. .data
  418.  
  419. int4         dd 140 dup(0)
  420.  
  421. .code
  422.              .     ; program establishes array values
  423.              .
  424.              .
  425.              mov    ax,@data
  426.              mov    es,ax
  427.              assume es:@data
  428.              lea    di,int4
  429.              mov    cx,140        ; search the entire array
  430.              call   maxi4
  431.              shl    ax,1          ; convert dword offset to word offset
  432.              shl    ax,1          ; convert word offset to byte offset
  433.              add    di,ax         ; ES:[DI] points to the maximum value
  434.                                   ; With max/min?4b, the offset of the
  435.                                   ; value is DI + (AX * BX).
  436.  
  437. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  438.  
  439. MONTHNAME:   returns a pointer to an ASCII string for specified month
  440. Source:      mname.asm ($mname.asm)
  441.  
  442. Call with:   AX = month (1 - 12, January = 1)
  443. Returns:     ES:[BX] = pointer to month name string
  444.              CX = length of month string
  445.              Note that the month name string is not zero-terminated
  446.              strndup may be used to copy the string to the near heap
  447. Uses:        ES, BX, CX
  448. Example:     mov    ax,month
  449.              call   monthname
  450.              jc     no_memory
  451.  
  452.  
  453.  
  454. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  455.  
  456. NFORMAT:     formats a numeric string
  457. Source:      nformat.asm (ltrim.asm, strspace.asm, heap.asm)
  458.  
  459. Call with:   DS:[SI] pointing to a numeric string (such as one produced
  460.              by i4tostr or i2tostr)
  461.              AL = number of decimal places in output string
  462.              BL = option code
  463.               where option 1 = negative numbers enclosed with parentheses
  464.                     option 2 = commas between thousands
  465.                     option 4 = decimals truncated (instead of rounded)
  466.              assumes DS @data
  467.              Note: you must initialize the near heap with MEMINIT before
  468.              using NFORMAT.  See STARTUP.ASM.
  469. Returns:     DS:[BX] pointing to formatted ASCIIZ string
  470. Uses:        BX, CF
  471.  
  472. Example:
  473.  
  474. include asm.inc
  475.  
  476. extrn  nformat:proc, i2tostr:proc
  477. extrn  meminit:proc
  478.  
  479. .data
  480.  
  481. ; reserve space for the heap
  482. heapsize equ 3000                ; should be plenty
  483. hbuffer  db heapsize  dup (0)
  484.  
  485. ; I'll use this numeric buffer
  486. nbuffer  db 12 dup(0)
  487.  
  488. .code
  489. ; program fragment assumes DS:@data
  490.          .
  491.          .
  492.          .
  493.          lea    bx,hbuffer
  494.          mov    ax,heapsize
  495.          call   meminit
  496.          mov    ax,-12345
  497.          lea    si,nbuffer
  498.          call   i2tostr
  499.          mov    al,2             ; 2 decimal places
  500.          mov    bl,1 OR 2        ; I want parentheses and commas
  501.          call   nformat          ; result returned at DS:[BX]
  502.                                  ; remember to release the formatted
  503.                                  ; string space with HFREE when you're
  504.                                  ; done with the string
  505.  
  506. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  507.  
  508. PATH:        finds paths in program enviornment
  509.              isolates each path in "PATH=" part of enviornment
  510. Source:      path.asm (strlen.asm)
  511.  
  512. Call with:   ES = PSP segment, AX = path number.  See STARTUP.ASM.
  513. Returns:     ES:[BX] -> path(AX) in enviornment block, CX = length of path
  514.              If CX = 0, path(AX) does not exist.  The first path in the
  515.              enviornment is path(0).
  516.              Note that the path string at ES:[BX] is NOT zero-terminated.
  517. Uses:        BX, CX, ES; flags and all other registers are saved
  518. Example:     
  519.  
  520. ; program startup code saves PSP segment
  521. include asm.inc
  522.  
  523. extrn   path:proc
  524.  
  525. stacksize equ 1024
  526. .stack stacksize
  527.  
  528. .data
  529. public pspseg
  530. pspseg dw ?                          ; storage for PSP segment
  531.  
  532. .code
  533. includelib asmlib
  534. start:
  535. ; start by pointing DS to DGROUP
  536.         mov     ax,@data
  537.         mov     ds,ax
  538.         assume  ds:@data
  539.  
  540. ; save PSP segment
  541.         mov     pspseg,es
  542.          .
  543.          .
  544.          .
  545. ; sometime later in the program
  546.         xor     ax,ax        ; start with the first path
  547. find_path:
  548.         mov     es,pspseg
  549.         call    path
  550.         jcxz    no_path      ; exit if no more paths, or else copy CX bytes
  551.                              ;  at ES:[BX] to some useful location (try
  552.                              ;  strndup).
  553.         inc     ax           ; look for next path
  554.         jmp     find_path
  555.  
  556. no_path:
  557.  
  558.  
  559. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  560.  
  561. QFNAME:      qualifies a filename
  562. Source:      qfname.asm
  563.  
  564. Call with:   DS:[BX] pointing to a filename; the filename may contain
  565.              drive specification and/or complete or partial path name.
  566.              Drive specification and path name not required.
  567. Returns:     DS:[SI] pointing to the full DRIVESPEC:\PATH\FILENAME
  568.              CX = length of full filename
  569.              Note that DS:[SI] points to QFName's buffer space; the next
  570.              call to QFName will return a new filename at the same address.
  571. Uses:        SI, CX, flags
  572. Example:
  573.  
  574. include asm.inc
  575.  
  576. .data
  577. docs   db '*.doc',0         ; search for .DOC files in current directory
  578.  
  579. .code
  580.        .
  581.        .
  582.        .
  583.        mov    ax,@data
  584.        mov    ds,ax
  585.        lea    bx,docs
  586.        call   qfname        ; returns 'drive:\path\*.doc'
  587.  
  588.  
  589. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  590.  
  591. RANDOM:      generates a near-random number
  592. Source:      random.asm
  593.  
  594. Call with:   no parameters
  595. Returns:     AX = near-random number between 0 and 65535
  596.              you may notice repeating patterns every few thousand calls
  597.              to Random.
  598. Uses:        AX
  599. Example:     call   random
  600.  
  601.  
  602.  
  603. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  604.  
  605. RSET:        right-justifies a string in a fixed field
  606. Source:      rset.asm (strlen.asm)
  607.  
  608. Call with:   ES:[DI] = address of field string
  609.              DS:[SI] = address of string to be justified in the field
  610.              Both strings must be zero-terminated (ASCIIZ).  The field
  611.              string may not contain any nul characters except for the
  612.              terminator.
  613. Returns:     CF = 0 if no error
  614.              CF = 1 if string was truncated to fit in the field
  615. Uses:        CF; all other flags and registers saved
  616. Example:     mov   ax,@data             ; in this case, both strings
  617.              mov   ds,ax                ; are in DGROUP
  618.              mov   es,ax
  619.              assume es:@data, ds:@data
  620.              lea   di,field             ; field string
  621.              lea   si,source            ; string to be justified in field
  622.              call  rset
  623.  
  624.  
  625. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  626.  
  627. RTRIM:       removes trailing blanks from an ASCIIZ string
  628. Source:      rtrim.asm (strlen.asm)
  629.  
  630. Call with:   DS:[BX] pointing to string
  631. Returns:     CX = new string length
  632. Uses:        CX
  633. Example:     lea    bx,string
  634.              call   rtrim
  635.  
  636.  
  637.  
  638. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  639.  
  640. SORTI2HI:    sort a signed array of 2-byte integers, highest first
  641. Source:      sorti2hi.asm
  642.  
  643. SORTI2LO:    sort a signed array of 2-byte integers, lowest first
  644. Source:      sorti2lo.asm
  645.  
  646. Call with:   ES:[DI] = address of first element of array to sort
  647.              CX = number of array elements
  648. Returns:     nothing
  649. Uses:        nothing; all registers and flags are saved
  650. Example:
  651.  
  652. include asm.inc
  653.  
  654. extrn    sorti2hi:proc
  655.  
  656. .data
  657.  
  658. i2data   dw 1500 dup(0)
  659.  
  660. .code
  661.  
  662.              .      ; program establishes data values
  663.              .
  664.              .
  665.          mov    ax,@data
  666.          mov    es,ax
  667.          assume es:@data
  668.          lea    di,i2data
  669.          mov    cx,1500
  670.          call   sorti2hi
  671.  
  672.  
  673.  
  674. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  675.  
  676. SORTI4HI:    sort a signed array of 4-byte integers, highest first
  677. Source:      tiny, small & medium: sorti4hi.asm
  678.              huge: sorti4hi.asm (lowES2hi.asm)
  679.  
  680. SORTI4LO:    sort a signed array of 4-byte integers, lowest first
  681. Source:      tiny, small & medium: sorti4lo.asm
  682.              huge: sorti4lo.asm (lowES2hi.asm)
  683.  
  684. Call with:   ES:[DI] = address of first element of array to sort
  685.              CX = number of array elements
  686. Returns:     nothing
  687. Uses:        nothing; all registers and flags are saved
  688. Example:
  689.  
  690. include asm.inc
  691.  
  692. extrn    sorti4hi:proc
  693.  
  694. .data
  695.  
  696. i4data   dd 1500 dup(0)
  697.  
  698. .code
  699.  
  700.              .      ; program establishes data values
  701.              .
  702.              .
  703.          mov    ax,@data
  704.          mov    es,ax
  705.          assume es:@data
  706.          lea    di,i4data
  707.          mov    cx,1500
  708.          call   sorti4hi
  709.  
  710.  
  711.  
  712. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  713.  
  714. STRTOI2:     converts an ASCII string to equivalent integer value
  715. STRNTOI2:    converts n bytes of an ASCII string to equivalent integer value
  716.              strtoi2 and strntoi2 ignore leading blanks and tabs, then read
  717.              the string until a non-numeric character is read.
  718.              strntoi2 reads a maximum of CX characters or until a
  719.              non-numeric character is read, whichever comes first.
  720. Source:      strtoi2.asm
  721.  
  722. STRTOI4:     converts an ASCII string to a long integer value
  723. STRNTOI4:    converts n bytes of an ASCII string to a long integer value
  724.              similar to strtoi2 and strntoi2, but returning a long integer
  725.              value in DX:AX.
  726. Source:      strtoi4.asm
  727.  
  728. Call with:   DS:[SI] = address of string
  729.              strntoi2/strntoi4 only: CX = number of bytes to read
  730. Returns:     AX = integer value, or DX:AX = long integer value
  731.              strtoix:  DS:[SI] points to character past terminating byte
  732.              strntoix: if CX = 0, DS:[SI] points to next character
  733.                      if CX <> 0, DS:[SI] points to character past
  734.                      terminating byte
  735.              BL = error code
  736.                 bit 0 if set = CR read before reading any numeric characters
  737.                 bit 1 if set = CR was the terminating character
  738.                 bit 6 if set = overflow; result in DX:AX is unusable
  739.                 bit 7 if set = result is unsigned; result is unusable if the
  740.                                value represented by the string was negative
  741. Uses:        AX, BX, CX, SI, flags
  742. Example:     lea    si,long_integer  ; near address of ASCII string
  743.              mov    cx,7             ; 7-byte field
  744.              call   strntoi2         ; return result as an integer in AX
  745.  
  746.  
  747.  
  748.  
  749. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  750.  
  751. STRCAT:      catenates (combines) two ASCIIZ strings
  752. Source:      strcat.asm (strdup.asm, strlen.asm, heap.asm)
  753.  
  754. Call with:   DS:[SI] = address of first string
  755.              DS:[BX] = address of second string
  756.              assumes DS:@data
  757. Returns:     if CF = 0, DS:[BX] = address of combined ASCIIZ string
  758.              if CF = 1, insufficient memory available in near heap
  759.              Note: you must initialize the near heap with MEMINIT before
  760.              using STRCAT.  See STARTUP.ASM.
  761. Uses:        BX, CX, CF
  762. Example:
  763.  
  764. include asm.inc
  765.  
  766. extrn  strcat:proc
  767.  
  768. .data
  769. string0 db 'this string goes first',0
  770. string1 db ' this one is added at the end of the first',0
  771.  
  772. .code
  773. ; program fragment assumes DS:@data
  774.        .
  775.        .
  776.        .
  777.        lea    si,string0       ; address of first string
  778.        lea    bx,string1       ; address of second string
  779.        call   strcat           ; result returned at DS:[BX]
  780.        jc     heap_is_full     ; original strings are undisturbed
  781.  
  782.  
  783.  
  784. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  785.  
  786. STRCHR:      search an ASCIIZ string for a specified character
  787. STRNCHR:     search n bytes of an ASCII string for a specified character
  788. Source:      strchr.asm (strlen.asm)
  789.  
  790. Call with:   DS:[BX] = pointer to ASCIIZ string
  791.              AL = character to find
  792.              CX = number of bytes to search (strnchr only)
  793. Returns:     CX = string length
  794.              if CF = 0, AX is the offset from DS:[BX] to matching character
  795.              in the source string
  796.              if CF = 1, no matching character found
  797. Uses:        CX, AX, CF
  798.  
  799. Example on next page
  800.  
  801. ; use STRNCHR to determine if a key pressed was a legal key
  802. include asm.inc
  803.  
  804. extrn   strnchr:proc, getkey:proc, toupper:proc
  805.  
  806. .data
  807.  
  808. valid_string db 'ABC123',27      ; keys 1,2,3,A,B,C and Esc
  809. valid_len    equ $-valid_string  ; number of valid keys
  810.  
  811. dispatch_table label word
  812.         dw akey, bkey, ckey, onekey, twokey, threekey, esckey
  813.  
  814. .code
  815. ; program fragment assumes DS:@data
  816.         .
  817.         .
  818.         .
  819. get_another:
  820.         lea   bx,valid_string ; DS:[BX] points to a string of valid keys
  821.         call  getkey          ; keycode returned in AX
  822.         shr   ah,1            ; test for extended keycode
  823.         jc    get_another     ; I'm not interested in extended keycodes today
  824.  
  825.         call  toupper         ; convert keycode to upper case
  826.         mov   cx,valid_len
  827.         call  strnchr
  828.         jc    get_another     ; CF = 1 if key pressed is not among the
  829.                               ; keys in the validation string
  830.         mov   bx,ax
  831.         shl   bx,1            ; convert byte offset to word offset
  832.         jmp   dispatch_table[bx]
  833.  
  834. akey:   .
  835.         .
  836.         .
  837.  
  838. bkey:   .
  839.         .
  840.         .
  841.  
  842. ckey:   .
  843.         .
  844.         .
  845.  
  846. ; etc
  847.  
  848.  
  849.  
  850. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  851.  
  852. STRCMP:      compare strings, case-sensetive
  853. Source:      strcmp.asm (strlen.asm)
  854.  
  855. Call with:   DS:[SI] pointing to string1
  856.              ES:[DI] pointing to string2
  857. Returns:     if string1 < string2, SF = 1
  858.              if string1 = string2, ZF = 1
  859.              if string1 > string2, SF = 0, ZF = 0
  860.              Note that 'A' < 'a',  and that 'a' < 'z'.  Both strings must
  861.              be NUL-terminated ASCII strings.
  862. Uses:        flags; all registers are saved
  863.  
  864. See also:    STRICMP, case-insensetive string comparison
  865.  
  866. Example:
  867.  
  868. include asm.inc
  869.  
  870. extrn   strcmp:proc
  871.  
  872. .data
  873.  
  874. string1 db 'Maple',0
  875. string2 db 'Oak',0
  876.  
  877. .code
  878. ; code fragment assumes DS:@data
  879.        .
  880.        .
  881.        .
  882. ; make sure ES = DS
  883.        mov      ax,ds
  884.        mov      es,ax
  885.        lea      si,string1        ; DS:[SI] points to string1
  886.        lea      di,string2        ; ES:[DI] points to string2
  887.        call     strcmp
  888.        je       they_are_the_same
  889.        jns      string2_GT_string1
  890.  
  891. ; string1 < string2
  892.        .
  893.        .
  894.  
  895.  
  896. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  897.  
  898. STRCPY:      copy an ASCIIZ string to existing buffer
  899. Source:      strcpy.asm (strlen.asm, strncpy.asm)
  900.  
  901. Call with:   ES:[BX] pointing to ASCIIZ string
  902.              DS:[SI] pointing to destination buffer
  903.              STRCPY assumes that the buffer is long enough to hold the
  904.              entire string.  The string's terminating NUL byte is not
  905.              copied to the buffer.
  906. Returns:     CX = string length
  907. Uses:        CX
  908. Example:
  909.  
  910. include asm.inc
  911.  
  912. extrn   strcpy:proc
  913.  
  914. .fardata
  915. fstring        db 'a far string',0
  916.  
  917. .data
  918. string_buffer  db 128 dup (?)
  919.  
  920. .code
  921. ; code fragment assumes DS:@data
  922.        .
  923.        .
  924.        .
  925. ; copy far string to DGROUP for convenient manipulation
  926.        mov    ax,@fardata
  927.        mov    es,ax
  928.        assume es:@fardata
  929.        mov    bx,offset @fardata:fstring
  930.        mov    si,offset @data:string_buffer
  931.        call   strcpy
  932.  
  933.  
  934. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  935.  
  936. STRICHR:     find the first byte in a string matching AL, case-insensetive
  937. STRNICHR:    find the first byte in n bytes matching AL, case-insensetive
  938. Source:      strichr.asm (strlen.asm, strchr.asm)
  939.  
  940. Call with:   DS:[BX] pointing to the first character of the string
  941.              AL = byte to find
  942.              (strnichr only) CX = number of bytes to search
  943. Returns:     if CF = 1, no match
  944.              if CF = 0, AX = offset from DS:[BX] of the first matching byte
  945. Uses:        AX, CF; all other flags and registers are saved
  946. Example:
  947.  
  948. .data
  949. string   db 'my old computer was a real slug',0
  950.  
  951. .code
  952.         .
  953.         .
  954.         .
  955.          mov   ax,@data
  956.          mov   ds,ax
  957.          assume  ds:@data
  958.  
  959.          mov   al,'W'         ; look for any "w" or "W"
  960.          lea   bx,string
  961.          call  strichr
  962.          jc    oops           ; cut outta here if not in the string
  963.                               ; else go on
  964.  
  965.  
  966.  
  967. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  968.  
  969. STRICMP:     compare strings, case-insensetive
  970. Source:      stricmp.asm (strlen.asm)
  971.  
  972. Call with:   DS:[SI] pointing to string1
  973.              ES:[DI] pointing to string2
  974. Returns:     if string1 < string2, SF = 1
  975.              if string1 = string2, ZF = 1
  976.              if string1 > string2, SF = 0, ZF = 0
  977.              Note that 'A' = 'a',  and that 'a' < 'z'.  Both strings must
  978.              be NUL-terminated ASCII strings.
  979. Uses:        flags; all registers are saved
  980.  
  981. See also:    STRCMP, case-sensetive string comparison
  982.  
  983. Example:
  984.  
  985. include asm.inc
  986.  
  987. extrn   stricmp:proc
  988.  
  989. .data
  990.  
  991. string1 db 'Maple',0
  992. string2 db 'Oak',0
  993.  
  994. .code
  995. ; code fragment assumes DS:@data
  996.        .
  997.        .
  998.        .
  999. ; make sure ES = DS
  1000.        mov      ax,ds
  1001.        mov      es,ax
  1002.        lea      si,string1        ; DS:[SI] points to string1
  1003.        lea      di,string2        ; ES:[DI] points to string2
  1004.        call     stricmp
  1005.        je       they_are_the_same
  1006.        jns      string2_GT_string1
  1007.  
  1008. ; string1 < string2
  1009.        .
  1010.        .
  1011.  
  1012.  
  1013. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1014.  
  1015. STRCPY:      copy an ASCIIZ string to existing buffer
  1016. Source:      strcpy.asm (strlen.asm, strncpy.asm)
  1017.  
  1018. Call with:   ES:[BX] pointing to ASCIIZ string
  1019.              DS:[SI] pointing to destination buffer
  1020.              STRCPY assumes that the buffer is long enough to hold the
  1021.              entire string.  The string's terminating NUL byte is not
  1022.              copied to the buffer.
  1023. Returns:     CX = string length
  1024. Uses:        CX
  1025. Example:
  1026.  
  1027. include asm.inc
  1028.  
  1029. extrn   strcpy:proc
  1030.  
  1031. .fardata
  1032. fstring        db 'a far string',0
  1033.  
  1034. .data
  1035. string_buffer  db 128 dup (?)
  1036.  
  1037. .code
  1038. ; code fragment assumes DS:@data
  1039.        .
  1040.        .
  1041.        .
  1042. ; copy far string to DGROUP for convenient manipulation
  1043.        mov    ax,@fardata
  1044.        mov    es,ax
  1045.        assume es:@fardata
  1046.        mov    bx,offset @fardata:fstring
  1047.        mov    si,offset @data:string_buffer
  1048.        call   strcpy
  1049.  
  1050.  
  1051. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1052.  
  1053. STRNCMP:     compare specified length of strings, case-sensetive
  1054. Source:      strncmp.asm
  1055.  
  1056. Call with:   DS:[SI] pointing to string1
  1057.              ES:[DI] pointing to string2
  1058.              CX = number of bytes to compare
  1059. Returns:     if string1 < string2, SF = 1
  1060.              if string1 = string2, ZF = 1
  1061.              if string1 > string2, SF = 0, ZF = 0
  1062.              Note that 'A' < 'a',  and that 'a' < 'z'.
  1063. Uses:        flags; all registers are saved
  1064.  
  1065. See also:    STRNICMP, case-insensetive string comparison,
  1066.              specified number of bytes
  1067.  
  1068. Example:
  1069.  
  1070. include asm.inc
  1071.  
  1072. extrn   strncmp:proc
  1073.  
  1074. .data
  1075.  
  1076. string1 db 'Maple',0
  1077. string2 db 'Oak',0
  1078.  
  1079. .code
  1080. ; code fragment assumes DS:@data
  1081.        .
  1082.        .
  1083.        .
  1084. ; make sure ES = DS
  1085.        mov      ax,ds
  1086.        mov      es,ax
  1087.        lea      si,string1        ; DS:[SI] points to string1
  1088.        lea      di,string2        ; ES:[DI] points to string2
  1089.        mov      cx,3              ; compare only first 3 characters
  1090.        call     strncmp
  1091.        je       they_are_the_same
  1092.        jns      string2_GT_string1
  1093.  
  1094. ; string1 < string2
  1095.        .
  1096.        .
  1097.  
  1098.  
  1099. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1100.  
  1101. STRNCPY:     copy CX bytes to an existing buffer
  1102. Source:      strncpy.asm
  1103.  
  1104. Call with:   ES:[BX] pointing to ASCII string
  1105.              DS:[SI] pointing to destination buffer
  1106.              CX = number of bytes to copy
  1107.              STRNCPY assumes that the buffer is long enough to hold the
  1108.              entire string
  1109. Returns:     nothing
  1110. Uses:        nothing; all registers and flags are saved
  1111. Example:
  1112.  
  1113. ; I want to copy a command line parameter to DGROUP
  1114.  
  1115. include asm.inc
  1116. extrn   getcmd:proc
  1117. extrn   strncpy:proc
  1118.  
  1119. .data
  1120. extrn   pspseg:word             ; PSP segment address was saved by STARTUP
  1121. string_buffer   db 128 dup (?)
  1122.  
  1123. .code
  1124. ; code fragment assumes DS:@data
  1125.        .
  1126.        .
  1127.        .
  1128.        mov      es,pspseg
  1129.        xor      ax,ax           ; first command line parameter
  1130.        call     getcmd          ; returns parameter at ES:[BX], length as CX
  1131.        jcxz     no_parameters
  1132.        lea      si,string_buffer
  1133.        call     strncpy
  1134.  
  1135. ; make it zero-terminated
  1136.        add      si,cx
  1137.        mov      byte ptr [si],0
  1138.  
  1139.  
  1140. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1141.  
  1142. STRNICMP:    compare specified length of strings, case-insensetive
  1143. Source:      strnicmp.asm
  1144.  
  1145. Call with:   DS:[SI] pointing to string1
  1146.              ES:[DI] pointing to string2
  1147.              CX = number of bytes to compare
  1148. Returns:     if string1 < string2, SF = 1
  1149.              if string1 = string2, ZF = 1
  1150.              if string1 > string2, SF = 0, ZF = 0
  1151.              Note that 'A' = 'a',  and that 'a' < 'z'.
  1152. Uses:        flags; all registers are saved
  1153.  
  1154. See also:    STRNCMP, case-sensetive string comparison, specified
  1155.              number of bytes.
  1156.  
  1157. Example:
  1158.  
  1159. include asm.inc
  1160.  
  1161. extrn   strnicmp:proc
  1162.  
  1163. .data
  1164.  
  1165. string1 db 'Maple',0
  1166. string2 db 'Oak',0
  1167.  
  1168. .code
  1169. ; code fragment assumes DS:@data
  1170.        .
  1171.        .
  1172.        .
  1173. ; make sure ES = DS
  1174.        mov      ax,ds
  1175.        mov      es,ax
  1176.        lea      si,string1        ; DS:[SI] points to string1
  1177.        lea      di,string2        ; ES:[DI] points to string2
  1178.        mov      cx,2              ; compare only first 2 characters
  1179.        call     strnicmp
  1180.        je       they_are_the_same
  1181.        jns      string2_GT_string1
  1182.  
  1183. ; string1 < string2
  1184.        .
  1185.        .
  1186.  
  1187.  
  1188. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1189.  
  1190. STRINS:      inserts string1 in string0 at specified offset.
  1191.              Creates new string in near heap; first part of new string
  1192.              is n bytes of string0; middle of new string is string1; end
  1193.              of new string is remainder of string0.
  1194. Source:      strins.asm (strlen.asm, heap.asm)
  1195.  
  1196. Call with:   DS:[SI] pointing to string0
  1197.              DS:[BX] pointing to string1
  1198.              AX = offset in string0 to insert string1 (0 >= AX >= 32767)
  1199.              Assumes DS:@data
  1200. Returns:     if CF = 1, insufficient memory in hear heap
  1201.              if CF = 0, DS:[BX] points to new string
  1202.              Note: you must initialize the near heap with MEMINIT before
  1203.              using STRINS.  See STARTUP.ASM.
  1204. Uses:        BX, CF
  1205. Example:
  1206.  
  1207. include asm.inc
  1208.  
  1209. extrn  strins:proc
  1210.  
  1211. .data
  1212. string0 db '1234567890',0
  1213. string1 db 'abcdefghij',0
  1214.  
  1215. .code
  1216.        .
  1217.        .
  1218.        .
  1219.        mov    ax,@data
  1220.        mov    ds,ax            ; dgroup
  1221.        assume ds:@data         ; tell MASM about it
  1222.        lea    si,string0       ; address of first string
  1223.        lea    bx,string1       ; address of second string
  1224.        mov    ax,3             ; string1 inserted after '123'
  1225.        call   strins           ; result returned at DS:[BX]
  1226.        jc     heap_is_full     ; original strings are undisturbed
  1227.  
  1228.  
  1229.  
  1230. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1231.  
  1232. STRDUP:      duplicates a string at ES:[BX]
  1233. Source:      strdup.asm (strlen.asm, heap.asm)
  1234.  
  1235. STRNDUP:     duplicates n bytes of a string at ES:[BX]
  1236. Source:      strndup (strdup.asm, heap.asm)
  1237.  
  1238. Call with:   ES:[BX] = address of source string
  1239.              assumes DS:@data
  1240.              (strndup) CX = number of bytes to duplicate
  1241.              String copied to near heap
  1242.              Source string need not be in same segment as heap
  1243.              strdup requires an ASCIIZ string; strndup duplicates CX
  1244.              characters at ES:[BX] whether zero-terminated or not.  The
  1245.              duplicate created by strdup or strndup will be an ASCIIZ
  1246.              string.
  1247.  
  1248. Returns:     if CF = 0, DS:[BX] = address of string copy
  1249.                         CX = string length
  1250.              if CF = 1, insufficient memory in near heap
  1251.              Note: you must initialize the near heap with MEMINIT before
  1252.              using STRDUP.  See STARTUP.ASM.
  1253. Uses:        BX, CX, CF; all other flags and registers are saved
  1254. Example:     mov  ax,@data
  1255.              mov  ds,ax
  1256.              mov  es,ax              ; in this case, the source string
  1257.                                      ; is in the data segment
  1258.              lea  bx,source          ; ES:[BX] = source address
  1259.              call strdup
  1260.              jc   oops               ; not enough memory if CF = 1
  1261.                                      ; otherwise, DS:[BX] = address
  1262.                                      ; of string copy
  1263.  
  1264.  
  1265. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1266.              
  1267. STRIPCHR:    remove all occurances of a character from an ASCIIZ string.
  1268. Source:      stripchr.asm (strlen.asm)
  1269.  
  1270. Call with:   DS:[BX] = string address
  1271.              AL = character to remove from the string
  1272. Returns:     CX = new string length
  1273. Uses:        CX
  1274. Example:     lea    bx,string        ; DS:[BX] -> string
  1275.              mov    al,'$'           ; remove "$" character from string
  1276.              call   stripchr
  1277.  
  1278.  
  1279. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1280.  
  1281. STRLEN:      finds length of an ASCIIZ string
  1282. Source:      strlen.asm
  1283.  
  1284. Call with:   DS:[BX] = address of the string
  1285. Returns:     CX = length of string excluding the terminating NUL
  1286. Uses:        CX
  1287. Example:     lea   bx,string
  1288.              call  strlen
  1289.  
  1290.  
  1291. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1292.  
  1293. STRLWR:      changes upper-case characters in a string to lower case
  1294. Source:      strlwr.asm
  1295.  
  1296. STRNLWR:     changes n bytes of a string to lower case
  1297. Source:      strnlwr.asm
  1298.  
  1299. Call with:   DS:[BX] = address of an ASCIIZ string
  1300.              CX = number of bytes (strnlwr only)
  1301. Returns:     nothing
  1302. Uses:        nothing
  1303. Example:     lea    bx,string
  1304.              call   strlwr
  1305.  
  1306.  
  1307.  
  1308. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1309.  
  1310. STRRCHR:     find the last byte in a string matching AL
  1311. STRNRCHR:    find the last byte in n bytes matching AL
  1312. Source:      strrchr.asm (strlen.asm)
  1313.  
  1314. Call with:   DS:[BX] pointing to the first character of the string
  1315.              AL = byte to find
  1316.              (strnrchr only) CX = number of bytes to search
  1317. Returns:     if CF = 1, no match
  1318.              if CF = 0, AX = offset from DS:[BX] of the last matching byte
  1319. Uses:        AX, CF; all other flags and registers are saved
  1320. Example:
  1321.  
  1322. .data
  1323. string   db 'my old computer was a real slug',0
  1324.  
  1325. .code
  1326.         .
  1327.         .
  1328.         .
  1329.          mov   ax,@data
  1330.          mov   ds,ax
  1331.          assume  ds:@data
  1332.  
  1333.          mov   al,'w'         ; look for the lower-case "w"
  1334.          lea   bx,string
  1335.          call  strrchr
  1336.          jc    oops           ; cut outta here if not in the string
  1337.                               ; else go on
  1338.  
  1339.  
  1340.  
  1341. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1342.  
  1343. STRREV:      reverses all characters in a string
  1344. STRNREV:     reverses n characters in a string
  1345. Source:      strrev.asm (strlen.asm)
  1346.  
  1347. Call with:   DS:[BX] pointing to the first character of the string
  1348.              CX = number of bytes in string to reverse (strnrev only)
  1349. Returns:     CX = string length
  1350. Uses:        CX; all other registers and flags saved
  1351. Example:     lea   bx,string          ; DS:[BX] points to ASCIIZ string
  1352.              call  strrev             ; also returns CX = string length
  1353.  
  1354.  
  1355.  
  1356. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1357.  
  1358. STRSPACE:    creates an ASCIIZ string filled with the space character,
  1359.              terminated with NUL
  1360. Source:      strspace.asm (heap.asm)
  1361.  
  1362. Call with:   AX = string length (not including terminating NUL)
  1363.              Assumes DS:@data
  1364. Returns:     if CF = 1, insufficient memory in near heap
  1365.              if CF = 0, DS:[BX] points to the new string
  1366.                         CX = string length (should be same as AX)
  1367.              Note: you must initialize the near heap with MEMINIT before
  1368.              using STRSPACE.  See STARTUP.ASM.
  1369. Uses:        CX, BX, CF
  1370. Example:     mov   ax,14              ; make a new string 14 characters long
  1371.              call  strspace
  1372.              jc    oops               ; not enough memory if CF = 1
  1373.              mov   string14,bx        ; else save pointer to string
  1374.  
  1375.  
  1376. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1377.  
  1378. STRSET:      sets all bytes of an ASCIIZ string to a specified character
  1379. STRNSET:     sets n bytes of an ASCIIZ string to a specified character
  1380. Source:      strset.asm (strlen.asm)
  1381.  
  1382. Call with:   DS:[BX] pointing to a valid ASCIIZ string
  1383.              AL = character
  1384.              CX = number of bytes to set (strnset only)
  1385. Returns:     CX = string length
  1386. Uses:        CX
  1387. Example:     lea   bx,string          ; DS:[BX] points to an ASCIIZ string
  1388.              mov   al,'*'
  1389.              call  strset
  1390.  
  1391.  
  1392.  
  1393.  
  1394. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1395.  
  1396. STRSTR:      finds the first match with a target string in a source string
  1397.              case sensetive
  1398. Source:      strstr.asm ($strstr.asm, strlen.asm)
  1399.  
  1400. STRISTR:     finds the first match with a target string in a source string
  1401.              case insensetive
  1402. Source:      stristr.asm (strstr.asm, strdup.asm, strlwr.asm, heap.asm)
  1403.  
  1404. STRRSTR:     finds the last match with a target string in a source string
  1405.              case sensetive
  1406. Source:      strrstr.asm (strrev.asm, $strstr.asm)
  1407.  
  1408. Call with:   ES:[DI] pointing to source string, DS:[SI] pointing to
  1409.              target string.
  1410.              STRISTR assumes DS:@data
  1411. Returns:     if CF = 0, AX = offset of target in source string.
  1412.              if CF = 1, no match
  1413.  
  1414.              Note: you must initialize the near heap with MEMINIT before
  1415.              using STRISTR.  See STARTUP.ASM.
  1416. Uses:        AX, CF; all other flags and registers are saved
  1417. Example:     mov   ax,@fardata
  1418.              mov   es,ax
  1419.             assume es:@fardata     ; source string is in far data area
  1420.              mov   ax,@data
  1421.              mov   ds,ax
  1422.             assume ds:@data
  1423.              lea   di,string       ; source = 'monday',0
  1424.              lea   si,substring    ; target = 'day',0
  1425.              call  strstr          ; in this example, strstr returns ax = 3
  1426.  
  1427.  
  1428. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1429.  
  1430. STRUPR:      changes lower-case characters in an ASCIIZ string to upper case
  1431. Source:      strupr.asm
  1432.  
  1433. STRNUPR:     changes lower-case characters in an n-length string to upper case
  1434. Source:      strnupr.asm
  1435.  
  1436. Call with:   DS:[BX] pointing to string
  1437.              (strnupr only) CX = number of bytes in string
  1438. Returns:     nothing
  1439. Uses:        nothing
  1440. Example:     mov    bx,offset string
  1441.              mov    cx,bytes
  1442.              call   strnupr
  1443.  
  1444.  
  1445.  
  1446. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1447.  
  1448. SWAPB:       swaps AX bytes at DS:[SI] with the same number at ES:[DI]
  1449. Source:      swapb.asm
  1450.              (huge model) swapb.asm, (lowds2hi.asm, lowes2hi.asm)
  1451.  
  1452. Call with:   DS:[SI] pointing to one of the data areas, ES:[DI] pointing
  1453.              to the other
  1454.              (tiny, small, medium) AX = number of bytes to swap
  1455.                             (huge) DX:AX = number of bytes to swap
  1456. Returns:     nothing
  1457. Uses:        nothing; all registers and flags are saved
  1458. Example:
  1459.  
  1460. include  asm.inc
  1461.  
  1462. extrn    swapb:proc
  1463.  
  1464. .data
  1465.  
  1466. string1  db 'this is string 1',0
  1467. string2  db 'this is string 2',0
  1468.  
  1469. strings  dw string1, string2         ; addresses of the strings
  1470.                                      ; this example will swap
  1471.                                      ; the string pointers
  1472.  
  1473. .code
  1474. public   stringswap
  1475. stringswap   proc
  1476. ; program fragment assumes DS:@data
  1477.          .
  1478.          .
  1479.          .
  1480.          lea   si,strings
  1481.          push  ds
  1482.          pop   es                    ; ES = DS
  1483.          mov   di,si
  1484.          mov   ax,2                  ; each string pointer is 2 bytes
  1485.          add   di,ax                 ; point to 2nd pointer
  1486.          call  swapb
  1487.  
  1488. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1489.  
  1490. WORDTOHEX:   Converts word data to hex (base 16) ASCIIZ string
  1491. Source:      wtohex.asm
  1492.  
  1493. Call with:   AX = word data
  1494.              DS:[SI] pointing to string buffer
  1495.               buffer must be at least 6 bytes
  1496. Returns:     DS:[SI] points to ASCIIZ string, hex format
  1497. Uses:        nothing
  1498. Example:
  1499.  
  1500. extrn   word2hex:proc
  1501. .data
  1502.  
  1503. hexbuf  db 6 dup(?)
  1504.  
  1505. .code
  1506.         .
  1507.         .
  1508.         .
  1509.         mov     ax,hexnumber
  1510.         call    wordtohex
  1511.  
  1512.